package activityservice

import (
	"context"
	"fmt"
	"games.com/server/internal/pkg/config"
	_ "github.com/go-sql-driver/mysql"
	"github.com/jmoiron/sqlx"
	"log"
)

var (
	insertActivitySQL    = `INSERT INTO activities (gm, activity_id, activity_name, start_time, end_time) VALUES (?, ?, ?, ?, ?)`
	deleteActivitySQL    = `DELETE FROM activities WHERE id = ?`
	updateActivitySQL    = `UPDATE activities SET gm = ?, activity_id = ?, activity_name = ?, start_time = ?, end_time = ? WHERE id = ?`
	queryActivityCntSQL  = `SELECT count(1) FROM activities`
	queryActivitySQL     = `SELECT id, gm, activity_id, activity_name, start_time, end_time FROM activities LIMIT ?, ?`
	queryActivityByIDSQL = `SELECT id, gm, activity_id, activity_name, start_time, end_time FROM activities WHERE id = ?`
)

type activityDAO struct {
	db *sqlx.DB
}

func NewActivityDAO(config *config.Config) (*activityDAO, error) {
	ad := &activityDAO{}

	log.Println(config.Dsn)

	db, err := sqlx.Connect("mysql", config.Dsn)
	if err != nil {
		return nil, fmt.Errorf("failed to open mysql connection, dsn:%s, err:%w", config.Dsn, err)
	}

	ad.db = db
	return ad, nil
}

func (ad *activityDAO) InsertActivity(ctx context.Context, activity *Activity) error {
	result, err := ad.db.ExecContext(ctx, insertActivitySQL, activity.Gm, activity.ActivityID, activity.ActivityName, activity.StartTime, activity.EndTime)
	if err != nil {
		return err
	}

	ID, err := result.LastInsertId()
	if err != nil {
		return err
	}

	activity.ID = int32(ID)

	return nil
}

func (ad *activityDAO) DeleteActivity(ctx context.Context, ID int32) error {
	_, err := ad.db.ExecContext(ctx, deleteActivitySQL, ID)
	if err != nil {
		return err
	}

	return nil
}

func (ad *activityDAO) UpdateActivity(ctx context.Context, record *Activity) error {
	_, err := ad.db.ExecContext(ctx, updateActivitySQL, record.Gm, record.ActivityID, record.ActivityName, record.StartTime, record.EndTime, record.ID)
	if err != nil {
		return err
	}

	return nil
}

func (ad *activityDAO) QueryActivityCnt(ctx context.Context) (int32, error) {
	var cnt int32

	err := ad.db.GetContext(ctx, &cnt, queryActivityCntSQL)
	if err != nil {
		return cnt, err
	}

	return cnt, nil
}

func (ad *activityDAO) QueryActivity(ctx context.Context, start, offset int32) ([]*Activity, error) {
	var ats []*Activity

	err := ad.db.SelectContext(ctx, &ats, queryActivitySQL, start, offset)
	if err != nil {
		return nil, err
	}

	return ats, nil
}

func (ad *activityDAO) QueryActivityByID(ctx context.Context, id int32) (*Activity, error) {
	var a Activity

	err := ad.db.GetContext(ctx, &a, queryActivityByIDSQL, id)
	if err != nil {
		return nil, err
	}

	return &a, nil
}
